﻿/************************************************************************

 This file is part of "10 Second Tim".

 "10 Second Tim" is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 "10 Second Tim" is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with "10 Second Tim".  If not, see <http://www.gnu.org/licenses/>.

************************************************************************/

// All code (c)2013 Scott Bevin. all rights reserved

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LDE;
using LDE.Input;
using LudumDare27.GameScreens;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace LudumDare27.Games.Game_2
{
	public class SkydiveAnim : ICharAnim
	{
		private float sinWave = 0.0f;
		private float rot = 0.0f;

		public void Update( float dt, Character c )
		{
			sinWave += dt * 15.0f;
			float sinVal = (float)Math.Sin( sinWave );

			rot = sinVal * 0.25f;
		}

		public Vector2 GetPos( Character c )
		{
			return c.Position;
		}

		public float GetRotation( Character c )
		{
			float baserot = c.Velocity.X;

			if ( baserot < -500.0f )
				baserot = -500.0f;

			if ( baserot > 500.0f )
				baserot = 500.0f;

			baserot += 500.0f;
			baserot /= 1000.0f;

			float rotAng = (float)Math.PI * 0.25f;
			baserot = -rotAng + ( rotAng * 2.0f * baserot );

			return (float)( Math.PI * 0.5f ) + baserot + rot;
		}
	}

	public class GameplayScreen : GameScreen
	{
		public static bool PlayedYet = false;
		private SpriteFont levelInfoFont;

		private ScreenBorder border;
		public Character m_playerchar = null;
		private Camera m_cam;
		private WhiteFadeScreen whiteFadeScreen = null;
		private SpriteFont f;

		private float levelTimer = 0.0f;
		private float deadTimer = 0.0f;

		private SoundEffect whiteNoiseSfx;
		private SoundEffectInstance whiteNoiseSfxInstance;
		private SoundEffect newLevelSfx;

		public class Box
		{
			public Sprite sprite;
			public Vector2 Pos;

			public Box( ContentManager content, Random rnd )
			{
				sprite = new Sprite( content.Load<Texture2D>( "Img/Box" ), 1 );
				Pos.X = -Defs.Game2.Width + ( ( Defs.Game2.Width * 2.0f ) * (float)rnd.NextDouble( ) );
				Pos.Y = 1000.0f + ( ( Defs.Game2.Height ) * (float)rnd.NextDouble( ) );
			}
		}

		public List<Box> m_boxes = new List<Box>( );

		public int Level;

		public GameplayScreen( int level )
			: base( true )
		{
			Level = level;
		}

		private Song backgroundMusic;

		override public void OnAdded( )
		{
			levelInfoFont = ContentManager.Load<SpriteFont>( "Fonts/DebugFont" );

			f = ContentManager.Load<SpriteFont>( "Fonts/DebugFont" );
			backgroundMusic = ( (LD27Game)Game ).PickSong( ContentManager );
			MediaPlayer.Play( backgroundMusic );
			MediaPlayer.IsRepeating = true;

			whiteNoiseSfx = ContentManager.Load<SoundEffect>( "Sfx/AboutToTrans" );
			whiteNoiseSfxInstance = whiteNoiseSfx.CreateInstance( );
			whiteNoiseSfxInstance.IsLooped = true;
			whiteNoiseSfxInstance.Play( );

			newLevelSfx = ContentManager.Load<SoundEffect>( "Sfx/NewLevel" );
			newLevelSfx.Play( );
			border = new ScreenBorder( ContentManager );

			int numBoxes = Level * Defs.Game2.LevelBoxMult;

			Random rnd = new Random( );

			for ( int i = 0; i < numBoxes; ++i )
			{
				m_boxes.Add( new Box( ContentManager, rnd ) );
			}

			m_cam = new Camera( Game.GraphicsDevice.PresentationParameters.BackBufferWidth,
					Game.GraphicsDevice.PresentationParameters.BackBufferHeight );
			m_cam.Zoom = 0.5f + (float)rnd.NextDouble( ) * 0.5f;
			m_cam.Rotation = m_cam.TargetRotation = (float)( Math.PI * 2.0f * rnd.NextDouble( ) );

			m_playerchar = new Character( ContentManager.Load<Texture2D>( "Img/Chars/GarrySkydive" ), ContentManager );
			m_playerchar.Velocity.Y = Defs.Game2.Gravity;
			m_playerchar.CurrentAnim = new SkydiveAnim( );
			m_playerchar.DontFlip = true;

			m_cam.Position = m_cam.TargetPosition = m_playerchar.Position;

			if ( !PlayedYet )
			{
				m_cam.Rotation = m_cam.TargetRotation = 0.0f;
				m_cam.Zoom = 0.5f;
			}

			base.OnAdded( );
		}

		public override void OnRemoved( )
		{
			PlayedYet = true;

			MediaPlayer.Stop( );

#if SILVERLIGHT
			whiteNoiseSfxInstance.Stop(  );
#else
			whiteNoiseSfxInstance.Stop( true );
#endif
			base.OnRemoved( );
		}

		override public void Update( float dt )
		{
			whiteNoiseSfxInstance.Volume = 0.0f;
			if ( levelTimer > 3.0f )
			{
				whiteNoiseSfxInstance.Volume = MathHelper.Clamp( 1.0f - ( ( 10.0f - levelTimer ) / 3.0f ), 0.0f, 1.0f );
			}
			if ( m_playerchar.Dead )
				levelTimer = 0.0f;

			levelTimer += dt;

			InputHandler input = Player.Get.GetInput( this );

			if ( levelTimer < 9.5f )
			{
				if ( input != null )
				{
					m_playerchar.Acceleration.X = input.GetStickVals( ).X * Defs.Game2.BaseMoveSpeed;
				}

				m_playerchar.Update( dt, 100000.0f, true );

				if ( !m_playerchar.Dead )
				{
					m_cam.TargetPosition = m_playerchar.Position;
					m_cam.TargetPosition.Y += 200.0f;

					Rectangle charRect = new Rectangle(
						(int)( m_playerchar.Position.X - m_playerchar.m_sprite.origin.X ),
						(int)( m_playerchar.Position.Y - m_playerchar.m_sprite.origin.Y ),
						(int)( m_playerchar.m_sprite.origin.X * 2.0f ),
						(int)( m_playerchar.m_sprite.origin.Y * 2.0f ) );

					foreach ( Box b in m_boxes )
					{
						Rectangle bRect = new Rectangle(
							(int)( b.Pos.X - b.sprite.origin.X ),
							(int)( b.Pos.Y - b.sprite.origin.Y ),
							(int)( b.sprite.origin.X * 2.0f ),
							(int)( b.sprite.origin.Y * 2.0f ) );

						if ( bRect.Intersects( charRect ) )
						{
							m_playerchar.Kill( );
							m_playerchar.CurrentAnim = new SkydiveDeadAnim( );
							deadTimer = 0.0f;

							break;
						}
					}
				}
				else
				{
					if ( ( deadTimer += dt ) >= 2.0f )
					{
						if ( whiteFadeScreen == null )
						{
							whiteFadeScreen = new WhiteFadeScreen( );
							GameScreenManager.AddGameScreen( whiteFadeScreen, null, GameScreenManager.AddGameScreenData.PositioningOptions.OnTop );
						}
					}
				}

				m_cam.Update( dt );
			}
			else
			{
				if ( whiteFadeScreen == null )
				{
					whiteFadeScreen = new WhiteFadeScreen( );
					GameScreenManager.AddGameScreen( whiteFadeScreen, null, GameScreenManager.AddGameScreenData.PositioningOptions.OnTop );
				}
			}

			if ( whiteFadeScreen != null && whiteFadeScreen.State == WhiteFadeScreen.States.FadedIn )
			{
				whiteFadeScreen.FadeOut( );

				if ( m_playerchar.Dead )
					GameScreenManager.AddGameScreen( new GameOverScreen( Level, false ), whiteFadeScreen, GameScreenManager.AddGameScreenData.PositioningOptions.BelowRef );
				else
					GameScreenManager.AddGameScreen( ( (LD27Game)Game ).ChooseNextGame( this, Level + 1 ), whiteFadeScreen, GameScreenManager.AddGameScreenData.PositioningOptions.BelowRef );

				this.KillScreen = true;
			}

			base.Update( dt );
		}

		override public void Render( float dt, GraphicsDevice gd, SpriteBatch sprites )
		{
			sprites.Begin( SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, null, null, null, m_cam.GetWorldMatrix( ) );

			foreach ( Box b in m_boxes )
				b.sprite.Render( sprites, b.Pos );

			m_playerchar.Render( sprites );

			// 			Vector2 p = m_playerchar.Position;
			// 			p.Y += 50.0f;
			// 			sprites.DrawString( f, levelTimer.ToString( ), p, Color.Green );

			sprites.End( );
			border.Render( gd, sprites );

			sprites.Begin( );

			InputHandler input = Player.Get.GetInput( this );

			if ( input != null && !PlayedYet )
			{
				string str = "";

				if ( input.FindDevice( GamePadInputDevice.DeviceTypeId, -1 ) != null )
				{
					str = "Left Stick: Left / Right [Avoid the boxes]";
				}
				else
				{
					str = "Arrows / A / D: Left / Right [Avoid the boxes]";
				}

				sprites.DrawString( levelInfoFont, str, new Vector2( Game.GraphicsDevice.PresentationParameters.BackBufferWidth * 0.5f, Game.GraphicsDevice.PresentationParameters.BackBufferHeight * 0.9f ),
					Color.Black, 0.0f, levelInfoFont.MeasureString( str ) * 0.5f, 1.0f, SpriteEffects.None, 1.0f );
			}

			sprites.End( );

			base.Render( dt, gd, sprites );
		}
	}
}